反向传播与矩阵求导

📋 完整训练流程

1. 前向传播
Z = XW + b
Y = σ(Z)
输入 → 输出
2. 计算损失
L = Loss(Y, T)
预测值 vs 真实值
衡量误差大小
3. 反向传播
∂L/∂W, ∂L/∂b, ∂L/∂X
链式法则求梯度
从输出向输入传播
4. 权重更新
W = W - lr × ∂L/∂W
b = b - lr × ∂L/∂b
沿梯度方向下降

📐 5个梯度公式

前向传播(带激活函数)
Z = XW + b  →  Y = σ(Z)
其中 σ 是激活函数(如 ReLU、Sigmoid、Tanh 等)
参数梯度公式(链式法则)运算GPU 核心说明
Y ∂L/∂Y = Y - T (损失函数对 Y 求导,是反向传播的起点,T 为真实标签) 矩阵相减 CUDA Core 反向传播起点
Z ∂L/∂Z = ∂L/∂Y ⊙ σ'(Z) (Y = σ(Z),⊙ 逐元素相乘,σ'(Z) 是激活函数导数) 逐元素相乘 CUDA Core 通过激活函数
W ∂L/∂W = ∂Z/∂W × ∂L/∂Z = Xᵀ × ∂L/∂Z (Z = XW + b,Z, W 变量,X, b 常量) 矩阵乘法 Tensor Core 输入转置 × 梯度
b ∂L/∂b = ∂L/∂Z × ∂Z/∂b = ∂L/∂Z × 1 = ∂L/∂Z (Z, b 变量,XW 常量,沿batch求和) 求和 CUDA Core 沿 batch 维度求和
X ∂L/∂X = ∂L/∂Z × ∂Z/∂X = ∂L/∂Z × Wᵀ (Z = XW + b,Z, X 变量,W, b 常量) 矩阵乘法 Tensor Core 梯度 × 权重转置

🖥️ 为什么逐元素运算用 CUDA Core,矩阵乘法用 Tensor Core?

运算类型硬件原因
矩阵乘法 (A × B) Tensor Core 专为 D = A×B+C 设计的专用硬件
逐元素运算 (A - B, A ⊙ B) CUDA Core 通用计算单元,处理任意运算

Tensor Core 只能执行固定的矩阵乘加操作(一次处理 4×4 或 8×8 小矩阵块),无法拆分或重新配置为其他运算。

📝 详细说明

∂L/∂Y 的计算(损失函数求导)

∂L/∂Y 由损失函数直接对预测值 Y 求导得到,是整个反向传播的起点。常见例子:

损失函数公式∂L/∂Y
MSE L = ½∥Y - T∥² Y - T
交叉熵 + Softmax L = -Σ Tᵢ log(Ŷᵢ) Ŷ - T

其中 T 是真实标签,Ŷ 是预测值。神奇的是:Softmax + 交叉熵组合的梯度极其简洁!

常见激活函数及其导数 σ'(Z)

  • ReLU:σ(z) = max(0, z),σ'(z) = 1 (z > 0) 或 0 (z ≤ 0)
  • Sigmoid:σ(z) = 1/(1+e⁻ᶻ),σ'(z) = σ(z)(1 - σ(z))
  • Tanh:σ(z) = tanh(z),σ'(z) = 1 - tanh²(z)

🎚️ 学习率 (Learning Rate)

权重更新公式(学习率在此引入)
W = W - lr × ∂L/∂W
b = b - lr × ∂L/∂b

lr — 学习率,通常 0.001 ~ 0.1
∂L/∂W — 损失对权重的梯度(更新方向)
- — 负号:梯度指向上升方向,我们要下降

🏔️ 直观理解:下山类比

📈

lr 太大

步子太大,跨过山谷
来回震荡、发散
loss 可能爆炸

╱↗╲
╱   ↖╲

lr 合适

步子适中,稳步下降
顺利到达谷底
loss 平稳下降

╱╲
 ↘ ●
🐢

lr 太小

步子太小,走得太慢
浪费大量时间
可能卡在局部最优

╱..╲
╱....╲

⚙️ 常见优化器中的学习率

SGD(基础)

W = W - lr × ∂L/∂W

最简单的梯度下降

Momentum(动量)

v = β×v + ∂L/∂W
W = W - lr × v

累积历史梯度,加速收敛

Adam(自适应)

m = β₁m + (1-β₁)g
v = β₂v + (1-β₂)g²
W = W - lr×m/(√v+ε)

自适应调整每个参数的学习率

📉 学习率调度 (Learning Rate Schedule)

  • 固定:lr = 0.001(简单任务)
  • 阶梯下降:每 N 轮 lr = lr × 0.1(图像分类)
  • 余弦退火:lr 按余弦曲线下降(Transformer)
  • Warmup:lr 从 0 逐渐增加,再下降(大模型训练)

❓ 学习率在哪个阶段参与?

阶段操作学习率参与?
前向传播 Y = XW + b ❌ 不参与
计算损失 L = Loss(Y, Y_true) ❌ 不参与
反向传播 ∂L/∂W, ∂L/∂b ❌ 不参与
权重更新 W = W - lr × ∂L/∂W
b = b - lr × ∂L/∂b
✅ 参与

💻 PyTorch 示例

import torch

# 数据和参数
X = torch.randn(32, 784)
W = torch.randn(784, 256, requires_grad=True)
b = torch.randn(256, requires_grad=True)
lr = 0.001

# 1. 前向传播
Y = X @ W + b
loss = Y.sum()

# 2. 反向传播(自动计算梯度)
loss.backward()
# W.grad = Xᵀ × ∂L/∂Y
# b.grad = sum(∂L/∂Y)

# 3. 权重更新(学习率在这里!)
with torch.no_grad():
    W -= lr * W.grad   # W = W - lr × ∂L/∂W
    b -= lr * b.grad   # b = b - lr × ∂L/∂b

🎯 总结

🔢

对标量求导

不是对矩阵求导
是对损失 L 求导
L 是一个标量值
所有梯度都是 ∂L/∂(参数)

⛓️

链式法则

梯度从输出向输入传播
每层乘以局部梯度
∂L/∂X = ∂L/∂Y × ∂Y/∂X
这就是"反向"的含义

📐

四个梯度

Y: 损失函数求导 (起点)
Z: ∂L/∂Y ⊙ σ'(Z) (逐元素乘)
W: Xᵀ × ∂L/∂Z (矩阵乘)
b: sum(∂L/∂Z) (沿batch求和)
X: ∂L/∂Z × Wᵀ (矩阵乘)

🎚️

学习率

在权重更新时引入
控制每次更新的步长
太大会震荡,太小会慢
常用值:0.001 ~ 0.01

完整的训练公式
前向传播: Z = XW + b → Y = σ(Z)
Y 的梯度: ∂L/∂Y = Y - T (损失函数求导,反向传播起点)
Z 的梯度: ∂L/∂Z = ∂L/∂Y ⊙ σ'(Z) (逐元素相乘)
W 的梯度: ∂L/∂W = Xᵀ × ∂L/∂Z (矩阵乘法)
b 的梯度: ∂L/∂b = sum(∂L/∂Z) (沿batch求和)
X 的梯度: ∂L/∂X = ∂L/∂Z × Wᵀ (矩阵乘法)
权重更新: W = W - lr × ∂L/∂W,   b = b - lr × ∂L/∂b